<?php
class Agitum_Model_User extends Agitum_Model_Object implements Zend_Auth_Adapter_Interface
{
	const GUEST_USER_ID = 1;
	const ENABLED = true;
	const DISABLED = false;
	
	protected $_t_class = 'Agitum_Model_DbTable_User';
	
	protected $roles = array();

	protected function init() 
	{
		parent::init();
		
		$this->_fields['password'] = array_merge($this->_fields['password'], 
				array('label' => 'Пароль', 'readOnly' => false, 'DATA_TYPE'=>'password'));
		
		$this->_fields['role'] = array_merge($this->_fields['role'], array('label' => 'Роль', 'readOnly' => false, 'DATA_TYPE' => 'reference'));
	}
		
	public function authenticate() 
	{
		$username = $this->name;
		$password = $this->password;
		
		$info = array(
			'code' => Zend_Auth_Result::FAILURE_UNCATEGORIZED,
			'identity' => 'guest',
			'messages' => array()
		);

		$db = Zend_Registry::get('Zend_Db');
		$select = $db->select();

        $expr = new Zend_Db_Expr(
            '(CASE WHEN ' .
            	$db->quoteInto( $db->quoteIdentifier('password', true) . ' = ?', $password )
            . ' THEN 1 ELSE 0 END) AS '
            . $db->quoteIdentifier( $db->foldCase('auth_match') )
            );

        $select->from( 'users', array('*', $expr))
                 ->where($db->quoteIdentifier('name', true) . ' = ?', $username )
                 ->where('active = true');

		$rows = $select->query()->fetchAll();

		if ( count($rows) < 1 ) {
			$info['code'] = Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND;
			$info['messages'][] = 'User not found';
		} else if (count($rows) > 1 ) {
			$info['code'] = Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS;
			$info['messages'][] = 'More than one user found';
		} else {

			$column = $db->foldCase('auth_match');
			$row = $rows[0];

        	if ($row[$column] != '1') {
            	$info['code'] = Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID;
            	$info['messages'][] = 'Wrong password';
        	} else {
        		$info['code'] = Zend_Auth_Result::SUCCESS;
        		$info['messages'][] = 'Authentication successful';

        		unset($row[$column]);

        		foreach ( $row as $key => $val ) {
        			$this->$key = $val;
        		}

        		$info['identity'] = $this;
			}
		}

		$result = new Zend_Auth_Result(
            $info['code'],
            $info['identity'],
            $info['messages']
        );

		return $result;
	}

	public function getGroups() 
	{
	    if ( count($this->groups) ) {
	        return $this->groups;
	    }
	    
	    $slot = new Agitum_Model_Cache_Slot_Group_List(array('user'=>$this->id));
	    $this->groups = $slot->load();
	    if (!$this->groups) 
	    {
    	    $db = Zend_Registry::get('Zend_Db');
    	    $select = $db->select();
    	    $select->from( array('g'=>'group') )
    	        ->joinCross( array('ug' => 'user_group') )
    	        ->where('ug.src_id = ?', $this->id)
    	        ->where('g.id = ug.dst_id')
    	        ->order('g.id')
    	        ;
    	    $rows = $select->query()->fetchAll();
    	    foreach ( $rows as $i => $row ) {
    	        array_push($this->groups, $row['name']);
    	        $slot->addTag(new Agitum_Model_Cache_Tag_Group($row['id']));
    	    }
    	    $slot->addTag(new Agitum_Model_Cache_Tag_User($this->id));
    	    $slot->save($this->groups);
	    }
	    return $this->groups;
	}
	
	public function setGroups($groups = array()) 
	{
	    $this->groups = $groups;
	}
	
	public function getRoles() 
	{
	    if ( count($this->roles) > 0 ) {
	        return $this->roles;
	    }
	    
	    $slot = new Agitum_Model_Cache_Slot_Role_List(array('user'=>$this->id));
	    $this->roles = $slot->load();
	    if ( !$this->roles ) 
	    {
    	    $db = Zend_Registry::get('Zend_Db');
    	    $select = $db->select();
    	    $select->from( array('r'=>'role') )
    	        ->joinCross( array('ug' => 'user_group') )
    	        ->joinCross( array('gr' => 'group_role') )
    	        ->where('ug.src_id = ?', $this->id)
    	        ->where('gr.src_id = ug.dst_id')
    	        ->where('r.id = gr.dst_id')
    	        ->order('r.id')
    	        ;
    	    $rows = $select->query()->fetchAll();
    	    foreach ( $rows as $i => $row ) {
    	        array_push($this->roles, $row['name']);
    	        $slot->addTag(new Agitum_Model_Cache_Tag_Role($row['id']));
    	    }
    	    array_push($this->roles, $this->role);
    	    $this->roles = array_unique($this->roles);
    	    $slot->addTag(new Agitum_Model_Cache_Tag_User($this->id));
    	    $slot->save($this->roles);
	    }
	    
	    return $this->roles;
	}

	public function setRoles($roles = array()) 
	{
	    $this->roles = $roles;
	}
}